package com.slz3.business.frame.exception;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.slz3.business.frame.response.RR;
import com.slz3.business.frame.response.ResInfo;
import com.slz3.business.frame.response.ResInfoRRDetail;
import com.slz3.business.frame.steward.Steward;
import com.slz3.business.frame.util.LocalDT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Mono;

@Slf4j
@Component
@Order(-5)
public class ExceptionHandler implements WebExceptionHandler {

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {

        log.error(exchange.getRequest().getURI().getPath());
        log.error(ex.getMessage(),ex);

        ServerHttpResponse res = exchange.getResponse();


        res.setStatusCode(HttpStatus.BAD_REQUEST);
        res.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);

        ResInfo resInfo = RR.initReqResInfo(exchange);
        resInfo.setDescription(ex.getMessage());

        ResInfoRRDetail detail = ((ResInfoRRDetail) resInfo.getDetail().get(RR.class.getSimpleName()));
        detail.setResTimestamp(System.currentTimeMillis());
        detail.setDuration(detail.getResTimestamp() - detail.getReqTimestamp());
        resInfo.setTimestamp(LocalDT.getDateTimeOfTimestamp(detail.getResTimestamp()).toString());

        //
        DataBuffer db;
        try {
            db = res.bufferFactory().wrap(Steward.writeValueAsBytes(resInfo));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            db = res.bufferFactory().wrap("{\"exception\": \"JsonProcessingException\"}".getBytes());
        }
        return res.writeWith(Mono.just(db));

    }

}
